const fs = require("fs");
const path = require("path");
// const watch = require("node-watch");
const minify = require("@node-minify/core");
const babelMinify = require("@node-minify/babel-minify");
const uglifyJS = require('@node-minify/uglify-js');

let watchFile = false;
process.argv.forEach((val, index) => {
  if (val === "--watch") {
    watchFile = true;
  }
});

let macro4libjs = {
  /* periperal */
  adc: 'JSE_HW_ADDON_ADC',
  dac: 'JSE_HW_ADDON_DAC',
  gpio: 'JSE_HW_ADDON_GPIO',
  i2c: 'JSE_HW_ADDON_I2C',
  spi: 'JSE_HW_ADDON_SPI',
  timer: 'JSE_HW_ADDON_TIMER',
  pwm: 'JSE_HW_ADDON_PWM',
  rtc: 'JSE_HW_ADDON_RTC',
  uart: 'JSE_HW_ADDON_UART',
  wdg: 'JSE_HW_ADDON_WDG',
  rtc: 'JSE_HW_ADDON_RTC',
  /* network */
  udp: 'JSE_NET_ADDON_UDP',
  tcp: 'JSE_NET_ADDON_TCP',
  mqtt: 'JSE_NET_ADDON_MQTT',
  http: 'JSE_NET_ADDON_HTTP',
  iot: 'JSE_NET_ADDON_IOT',
  network: ['JSE_NET_ADDON_CELLULAR', 'JSE_NET_ADDON_WIFI'],
  /* system */
  init: 'JSE_CORE_ADDON_INITJS',
  fs: 'JSE_CORE_ADDON_FS',
  lpm: 'JSE_CORE_ADDON_LPM',
  wakelock: 'JSE_CORE_ADDON_WAKELOCK',
  /* adavanced */
  audio: 'JSE_ADVANCED_ADDON_AUDIO',
  tts: 'JSE_ADVANCED_ADDON_TTS',
  ui: 'JSE_ADVANCED_ADDON_UI',
  vm: 'JSE_ADVANCED_ADDON_UI',
  keypad: 'JSE_ADVANCED_ADDON_KEYPAD',
  /* others will not include in macro */
}

let template = `
/*
* Copyright (C) 2015-2020 Alibaba Group Holding Limited
* This file autogenerated for jsapi
*/

#include <stdio.h>
#include <string.h>
#include "amp_config.h"
#include "addons/libjs.h"

#ifdef JSE_HIGHLEVEL_JSAPI

`;

// Async/Await
async function doMinifyLibs(content) {
  const data = await minify({
    compressor: babelMinify,
    content,
    options: {
      babelrc: ".babelrc",
    },
  });
  return data;
}

// 读取lib文件
async function doBuildLibs() {
  let files = fs.readdirSync("./lib");

  template += `libjs_entry_t LIBJS_ENTRIES[] = {\n`;
  for (let i = 0; i < files.length; i++) {
    let file = files[i];
    console.log(file);
    const filePath = `./lib/${file}`;
    const fileInfo = fs.statSync(filePath);
    if (fileInfo.isDirectory()) {
      return;
    }

    // 转译 + 压缩
    const fileContent = fs.readFileSync(filePath);
    console.log(fileContent);

    try {
      // 转译 + 压缩后的数据，生成C代码
      let minifyContent = await doMinifyLibs(fileContent);
      minifyContent = minifyContent.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
      console.log(minifyContent);
      let fileName = path.basename(filePath, ".js");

      if(macro4libjs.hasOwnProperty(fileName)) {
        console.log(macro4libjs[fileName]);
        if(typeof macro4libjs[fileName] !== 'string') {
          template += '#if ';
          macro4libjs[fileName].forEach((macro, index) => {
            template += `defined(${macro})`;
            if(index < macro4libjs[fileName].length - 1){
              template += ' || ';
            }
          });
          template += `\n     {"${fileName}", "${minifyContent}"},\n#endif\n\n`;
        }
        else {
          template += `#ifdef ${macro4libjs[fileName]}\n     {"${fileName}", "${minifyContent}"},\n#endif\n\n`;
        }
      }
      else {
        template += `    {"${fileName}", "${minifyContent}"},\n\n`;
      }
    } catch (e) {
      console.log(e);
      process.exit(-1);
    }
  }
  const initContent = await doBuildInit();
  console.log(initContent);
  template += `#ifdef ${macro4libjs['init']}\n    {"init", "${initContent}"},\n#endif\n\n`;
  template += "};\n\n";
  template += "int libjs_num = (sizeof(LIBJS_ENTRIES)/ sizeof(LIBJS_ENTRIES[0]));\n\n#endif /* JSE_HIGHLEVEL_JSAPI */\n"
  console.log(template);
  // 写入到文件
  fs.writeFileSync('../engine/duktape_engine/addons/libjs.c', template);
}

async function doBuildInit() {
  try {
    // 转译 + 压缩后的生成init.js
    await minify({
      compressor: uglifyJS,
      input: 'init/*.js',
      output: 'init.js',
    });
    // 打包到c代码，转义部分字符（引号和反斜杠）
    let initContent = fs.readFileSync('./init.js').toString().replace(/"/g, "\\\"");
    return initContent;
  } catch (e) {
    console.log(e);
    process.exit(-1);
  }
}

doBuildLibs();
doBuildInit();
